package com.ruoyi.mentor.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.ChooseStatusConstants;
import com.ruoyi.common.constant.ExamineStatusConstants;
import com.ruoyi.common.constant.UserTypeConstants;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.mentor.bo.ChooseQueryBo;
import com.ruoyi.mentor.bo.StudentAddBo;
import com.ruoyi.mentor.bo.StudentEditBo;
import com.ruoyi.mentor.bo.StudentQueryBo;
import com.ruoyi.mentor.domain.*;
import com.ruoyi.mentor.mapper.StudentMapper;
import com.ruoyi.mentor.service.IStudentService;
import com.ruoyi.mentor.vo.ExportStudentVo.ExportStudentVo;
import com.ruoyi.mentor.vo.RoundVo;
import com.ruoyi.mentor.vo.StudentDetailInfoVo;
import com.ruoyi.mentor.vo.StudentVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.Null;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 研究生信息Service业务层处理
 *
 * @author LH
 * @date 2021-05-21
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements IStudentService {

    @Autowired
    StudentDetailServiceImpl studentDetailService;

    @Autowired
    StuMemberInfoServiceImpl memberInfoService;

    @Autowired
    SubjectServiceImpl subjectService;

    @Autowired
    InstructorServiceImpl instructorService;

    @Autowired
    ChooseServiceImpl chooseService;

    @Autowired
    SpotServiceImpl spotService;

    @Autowired
    RoundServiceImpl roundService;

    @Autowired
    ExamineServiceImpl examineService;

    @Autowired
    UpdatePasswordServiceImpl updatePasswordService;


    @Override
    public StudentVo queryById(Long id){
        return getVoById(id, StudentVo.class);
    }

    @Override
    public TableDataInfo<StudentVo> queryPageList(StudentQueryBo bo) {
        PagePlus<Student, StudentVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), StudentVo.class);

        //查询学科信息表
        List<StudentVo> collect = result.getRecordsVo().stream().map(item -> {
            Subject byId = subjectService.getById(item.getSubId());
            item.setSubName(byId.getSubName());
            return item;
        }).collect(Collectors.toList());

        result.setRecordsVo(collect);

        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<ExportStudentVo> queryList(StudentQueryBo bo) {
        List<StudentVo> studentVos = listVo(buildQueryWrapper(bo), StudentVo.class);
        List<ExportStudentVo> collect = studentVos.stream().map(item -> {
            ExportStudentVo exportStudentVo = new ExportStudentVo();
            Long stuId = item.getId();
            Student student = getById(stuId);
            BeanUtils.copyProperties(student, exportStudentVo);

            Choose choose = chooseService.getOne(new QueryWrapper<Choose>().eq("stu_id", stuId).eq("choose_status",2));
            if(choose!=null){
                Subject chooseSub = subjectService.getById(choose.getSubId());
                Instructor instructor = instructorService.getById(choose.getInsId());
                exportStudentVo.setInsName(instructor.getInsName());
                exportStudentVo.setInsCardId(instructor.getInsCartId());
                exportStudentVo.setChooseSubName(chooseSub.getSubName());
            }



            StudentDetail studentDetail = studentDetailService.getOne(new QueryWrapper<StudentDetail>().eq("stu_id", stuId));
            if (studentDetail != null) {
                BeanUtils.copyProperties(studentDetail, exportStudentVo);
            }
            List<StuMemberInfo> memberInfos = memberInfoService.list(new QueryWrapper<StuMemberInfo>().eq("stu_id", stuId));
            if (memberInfos != null && memberInfos.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (StuMemberInfo memberInfo : memberInfos) {
                    StringBuilder t = new StringBuilder();
                    t.append(memberInfo.getName() + "|");
                    t.append(memberInfo.getRelation() + "|");
                    t.append(memberInfo.getGender() + "|");
                    t.append(memberInfo.getPhone() + "|");
                    t.append(memberInfo.getNation() + "|");
                    t.append(memberInfo.getAddress() + "|");
                    t.append(memberInfo.getProfession() + "|");
                    sb.append(t + "##");
                }
                exportStudentVo.setMemberInfo(sb.toString());
            }
            Subject subject = subjectService.getById(student.getSubId());
            if (subject != null) {
                exportStudentVo.setSubName(subject.getSubName());
            }

            return exportStudentVo;
        }).collect(Collectors.toList());
        return collect;
    }

    private LambdaQueryWrapper<Student> buildQueryWrapper(StudentQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Student> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getSubId()!=null,Student::getSubId,bo.getSubId());
        lqw.eq(bo.getIsChoose()!=null,Student::getIsChoose,bo.getIsChoose());
        lqw.like(StrUtil.isNotBlank(bo.getStuName()), Student::getStuName, bo.getStuName());
        lqw.eq(bo.getStuGender()!=null, Student::getStuGender, bo.getStuGender());
        lqw.eq(StrUtil.isNotBlank(bo.getStuExamId()), Student::getStuExamId, bo.getStuExamId());
        lqw.eq(StrUtil.isNotBlank(bo.getStuCardId()), Student::getStuCardId, bo.getStuCardId());
        lqw.eq(StrUtil.isNotBlank(bo.getStuBirth()), Student::getStuBirth, bo.getStuBirth());
        lqw.eq(StrUtil.isNotBlank(bo.getStuGraduateDate()), Student::getStuGraduateDate, bo.getStuGraduateDate());
        lqw.eq(bo.getExamineStatus() != null, Student::getExamineStatus, bo.getExamineStatus());
        lqw.orderByAsc(Student::getExamineStatus);
        lqw.orderByAsc(Student::getIsChoose);
        return lqw;
    }

    @Override
    public Boolean insertByAddBo(StudentAddBo bo) {
        Student add = BeanUtil.toBean(bo, Student.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(StudentEditBo bo) {
        Student update = BeanUtil.toBean(bo, Student.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Student entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public StudentDetailInfoVo getStudentDetailInfo(Long studentId) {
        StudentDetailInfoVo res = new StudentDetailInfoVo();
        //查询基本信息
        Student student = getById(studentId);
        StudentDetail detail = studentDetailService.getOne(new QueryWrapper<StudentDetail>().eq("stu_id", studentId));
        List<StuMemberInfo> members = memberInfoService.list(new QueryWrapper<StuMemberInfo>().eq("stu_id", studentId));
        if (members!=null&&members.size()>0){
            res.setMembers(members);
        }
        BeanUtils.copyProperties(student,res);
        if (detail!=null){
            BeanUtils.copyProperties(detail,res);
        }
        return res;
    }

    /**
     * 如果已经存在，就改变为修改学生信息
     * @param studentDetailInfoVo
     */
    @Transactional
    @Override
    public void saveStudent(StudentDetailInfoVo studentDetailInfoVo) {
        //保存基本信息
        if (studentDetailInfoVo.getStuId()==null){
            Student student = new Student();
            StudentDetail studentDetail = new StudentDetail();
            BeanUtils.copyProperties(studentDetailInfoVo,student);
            student.setUserId(studentDetailInfoVo.getUserId());
            student.setExamineStatus(ExamineStatusConstants.EXAMINE_ING);
            save(student);


            BeanUtils.copyProperties(studentDetailInfoVo,studentDetail);
            studentDetail.setStuId(student.getId());
            studentDetailService.save(studentDetail);

            List<StuMemberInfo> members = studentDetailInfoVo.getMembers();
            if (members!=null&&members.size()>0){
                members = members.stream().map(item->item.setStuId(student.getId())).collect(Collectors.toList());
            }

            memberInfoService.saveBatch(members);
        }else {
            //修改信息
            Student student = new Student();
            StudentDetail studentDetail = new StudentDetail();


            BeanUtils.copyProperties(studentDetailInfoVo,student);
            student.setUserId(studentDetailInfoVo.getUserId());
            student.setExamineStatus(ExamineStatusConstants.EXAMINE_ING);
            student.setId(studentDetailInfoVo.getStuId());
            updateById(student);


            BeanUtils.copyProperties(studentDetailInfoVo,studentDetail);
            studentDetail.setStuId(student.getId());
            studentDetailService.update(studentDetail,new QueryWrapper<StudentDetail>().eq("stu_id",studentDetail.getStuId()));

            List<StuMemberInfo> members = studentDetailInfoVo.getMembers();
            if (members!=null&&members.size()>0){
                members = members.stream().map(item->{
                    item.setStuId(student.getId());
                    item.setId(null);
                    return item;
                }).collect(Collectors.toList());
            }
            memberInfoService.remove(new QueryWrapper<StuMemberInfo>().eq("stu_id",student.getId()));
            memberInfoService.saveBatch(members);
        }

    }

    @Override
    public StudentDetailInfoVo getStudentDetailInfoByUserId(Long userId) {
        StudentDetailInfoVo res = new StudentDetailInfoVo();
        //查询基本信息
        Student student = getOne(new QueryWrapper<Student>().eq("user_id", userId));
        if (student==null){
            return null;
        }
        res.setUserId(userId);
        res.setStuId(student.getId());
        StudentDetail detail = studentDetailService.getOne(new QueryWrapper<StudentDetail>().eq("stu_id", student.getId()));
        List<StuMemberInfo> members = memberInfoService.list(new QueryWrapper<StuMemberInfo>().eq("stu_id", student.getId()));
        if (members!=null&&members.size()>0){
            res.setMembers(members);
        }
        BeanUtils.copyProperties(student,res);
        if (detail!=null){
            BeanUtils.copyProperties(detail,res);
        }
        return res;
    }

    /**
     * 选择导师
     *
     * @param insId
     * @param stuId
     */
    @Override
    @Transactional
    public void chooseIns(Long insId, Long stuId,Long subId,Integer type) {

        //TODO 在并发情况下，一个学生连续点击提交按钮时，会发生重复提交问题，可以考虑接口幂等性设计，或者加锁设计

        Instructor instructor = instructorService.getById(insId);
        Student student = getById(stuId);
        Spot spot = spotService.getOne(new QueryWrapper<Spot>().eq("ins_id", insId).eq("sub_id", subId));
        if (spot.getCheckedNumber()==spot.getPgNumber()){
            throw new CustomException("当前导师选择人数已满");
        }
        Choose choose = new Choose();
        if (type==1){
            RoundVo round = roundService.isSelectTime(0);
            if (!(round.getStuStart().before(new Date())&&round.getStuEnd().after(new Date()))){
                throw new CustomException("未到选择时间");
            }
            choose.setRoundId(round.getId());
        }


        if (type==1){
            choose.setChooseStatus(ChooseStatusConstants.CHOOSE_ING);
        }else {
            choose.setChooseStatus(ChooseStatusConstants.CHOOSE_SUCCESS);
        }

        choose.setStuConfirmDatetime(new Date());
        choose.setYear(spot.getYear());
        choose.setStuId(stuId);
        choose.setInsId(insId);
        choose.setSubId(subId);

        chooseService.save(choose);
        student.setIsChoose(1);
        spot.setCheckedNumber(spot.getCheckedNumber()+1);
        spotService.updateById(spot);
        updateById(student);
    }

    /**
     * 取消导师选择
     *
     * @param insId 导师id
     * @param stuId 学生id
     * @param subId 学科id
     */
    @Override
    @Transactional
    public void cancelChooseIns(Long insId, Long stuId, Long subId) {
        Student student = getById(stuId);
        student.setIsChoose(0);
        updateById(student);

        //获取招生信息
        Spot spot = spotService.getSpot(insId, subId);

        if (spot==null){
            throw new CustomException("获取招生信息失败,请联系管理员");
        }
        chooseService.remove(new QueryWrapper<Choose>().eq("stu_id",stuId).eq("ins_id",insId).eq("year",spot.getYear()));
        spot.setCheckedNumber(spot.getCheckedNumber()-1);

        spotService.updateById(spot);
    }

    /**
     * 导师拒绝后，学生需要确认
     *
     * @param insId
     * @param stuId
     */
    @Override
    @Transactional
    public void confirmStatus(Long insId, Long stuId) {
        Student student = new Student();
        student.setId(stuId);
        student.setIsChoose(0);
        updateById(student);

        //删除选择表
        chooseService.remove(new QueryWrapper<Choose>().eq("ins_id",insId).eq("stu_id",stuId));

    }

    /**
     * 根据用户id删除学生所有信息
     * @param userId
     */
    @Override
    @Transactional
    public void removeStudentByUserId(Long userId) {
        Student student = getOne(new QueryWrapper<Student>().eq("user_id", userId));
        if (student!=null){
            studentDetailService.remove(new QueryWrapper<StudentDetail>().eq("stu_id",student.getId()));
            memberInfoService.remove(new QueryWrapper<StuMemberInfo>().eq("stu_id",student.getId()));
            chooseService.remove(new QueryWrapper<Choose>().eq("stu_id",student.getId()));
            examineService.remove(new QueryWrapper<Examine>().eq("si_id",student.getId()).eq("user_type", UserTypeConstants.ROLE_STUDENT));
            updatePasswordService.remove(new QueryWrapper<UpdatePassword>().eq("user_id",userId));
            removeById(student);
        }

    }

    /**
     * 导出该老师的学生信息
     *
     * @param insId
     * @return
     */
    @Override
    public List<ExportStudentVo> exportStudentByInsId(Long insId) {

        Instructor instructor = instructorService.getById(insId);


        List<ExportStudentVo> collect = chooseService.list(new QueryWrapper<Choose>().eq("ins_id", insId).eq("choose_status", 2)).stream().map(item -> {
            ExportStudentVo exportStudentVo = new ExportStudentVo();
            Long stuId = item.getStuId();
            Student student = getById(stuId);
            BeanUtils.copyProperties(student, exportStudentVo);

            Subject chooseSubject = subjectService.getById(item.getSubId());
            exportStudentVo.setChooseSubName(chooseSubject.getSubName());

            exportStudentVo.setInsName(instructor.getInsName());
            exportStudentVo.setInsCardId(instructor.getInsCartId());

            StudentDetail studentDetail = studentDetailService.getOne(new QueryWrapper<StudentDetail>().eq("stu_id", stuId));
            if (studentDetail != null) {
                BeanUtils.copyProperties(studentDetail, exportStudentVo);
            }
            List<StuMemberInfo> memberInfos = memberInfoService.list(new QueryWrapper<StuMemberInfo>().eq("stu_id", stuId));
            if (memberInfos != null && memberInfos.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (StuMemberInfo memberInfo : memberInfos) {
                    StringBuilder t = new StringBuilder();
                    t.append(memberInfo.getName() + "|");
                    t.append(memberInfo.getRelation() + "|");
                    t.append(memberInfo.getGender() + "|");
                    t.append(memberInfo.getPhone() + "|");
                    t.append(memberInfo.getNation() + "|");
                    t.append(memberInfo.getAddress() + "|");
                    t.append(memberInfo.getProfession() + "|");
                    sb.append(t + "##");
                }
                exportStudentVo.setMemberInfo(sb.toString());
            }
            Subject subject = subjectService.getById(student.getSubId());
            if (subject != null) {
                exportStudentVo.setSubName(subject.getSubName());
            }

            return exportStudentVo;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 导出所有志愿选择信息
     *
     * @return
     */
    @Override
    public List<ExportStudentVo> exportAllStudent(ChooseQueryBo bo) {

        QueryWrapper<Choose> chooseQueryWrapper = new QueryWrapper<>();
        chooseQueryWrapper
                .eq("year",Calendar.getInstance().get(Calendar.YEAR))
                .eq("choose_status", 2).orderByAsc("ins_id")
                .eq(bo.getInsId()!=null,"ins_id",bo.getInsId())
                .eq(bo.getYear()!=null,"year",bo.getYear())
                .eq(bo.getChooseSubId()!=null,"sub_id",bo.getSubId())
                .orderByDesc("ins_id");
        List<ExportStudentVo> collect = chooseService.list(chooseQueryWrapper).stream().map(item -> {
            ExportStudentVo exportStudentVo = new ExportStudentVo();
            Long stuId = item.getStuId();
            Student student = getById(stuId);
            BeanUtils.copyProperties(student, exportStudentVo);

            Subject chooseSubject = subjectService.getById(item.getSubId());
            exportStudentVo.setChooseSubName(chooseSubject.getSubName());


            Instructor instructor = instructorService.getById(item.getInsId());
            exportStudentVo.setInsName(instructor.getInsName());
            exportStudentVo.setInsCardId(instructor.getInsCartId());

            StudentDetail studentDetail = studentDetailService.getOne(new QueryWrapper<StudentDetail>().eq("stu_id", stuId));
            if (studentDetail != null) {
                BeanUtils.copyProperties(studentDetail, exportStudentVo);
            }
            List<StuMemberInfo> memberInfos = memberInfoService.list(new QueryWrapper<StuMemberInfo>().eq("stu_id", stuId));
            if (memberInfos != null && memberInfos.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (StuMemberInfo memberInfo : memberInfos) {
                    StringBuilder t = new StringBuilder();
                    t.append(memberInfo.getName() + "|");
                    t.append(memberInfo.getRelation() + "|");
                    t.append(memberInfo.getGender() + "|");
                    t.append(memberInfo.getPhone() + "|");
                    t.append(memberInfo.getNation() + "|");
                    t.append(memberInfo.getAddress() + "|");
                    t.append(memberInfo.getProfession() + "|");
                    sb.append(t + "##");
                }
                exportStudentVo.setMemberInfo(sb.toString());
            }
            Subject subject = subjectService.getById(student.getSubId());
            if (subject != null) {
                exportStudentVo.setSubName(subject.getSubName());
            }

            return exportStudentVo;
        }).collect(Collectors.toList());
        return collect;
    }
}
